package org.singledog.form.builder.parser.freemarker.loader;

import freemarker.cache.TemplateLoader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
public class ClasspathTemplateLoader implements TemplateLoader {

    private final List<String> baseClasspathList;

    public ClasspathTemplateLoader(String ... baseClasspaths) {
        Assert.notEmpty(baseClasspaths, "base classpath can't be null !");
        ArrayList<String> list = new ArrayList<>();
        for (String path : baseClasspaths) {
            if (!path.endsWith("/")) {
                path = path + "/";
            }

            path = path.replaceAll("(?i)classpath(\\*)?:", "");
            list.add(path);
        }

        baseClasspathList = Collections.unmodifiableList(list);
    }


    @Override
    public Object findTemplateSource(String name) throws IOException {
        if (!name.endsWith(".ftl")) {
            name = name + ".ftl";
        }

        for (String basePath : baseClasspathList) {
            Resource resource = getExistsResource(basePath + name);
            if (resource != null) {
                return resource;
            }
        }

        return null;
    }

    private Resource getExistsResource(String path) {
        Resource resource = new ClassPathResource(path);
        if (resource.exists() && resource.isReadable()) {
            return resource;
        }

        return null;
    }

    @Override
    public long getLastModified(Object templateSource) {
        if (templateSource instanceof Resource) {
            try {
                return ((Resource) templateSource).lastModified();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return 0;
    }

    @Override
    public Reader getReader(Object templateSource, String encoding) throws IOException {
        if (templateSource instanceof Resource) {
            return new InputStreamReader(((Resource) templateSource).getInputStream(), encoding);
        }

        return null;
    }

    @Override
    public void closeTemplateSource(Object templateSource) throws IOException {

    }
}
